
mod simple;
pub mod general;
mod filter;
pub mod aggregate;
pub mod window;
pub mod follow;
mod element;
pub mod metadata;
pub mod util;

/*
    PhysicalPlanExpr就是对单个事件数据的判断或处理
    这里定一个原则：PhysicalPlanExprArg仅有三种类型，ConfValue/RealValue/ElementValue，
    所有的PhysicalPlanExpr都需要尽量去适应这三种类型的各种组合形成的参数，以避免外围递归函数组合太过于复杂。
    这么定还有一层考虑，那就是避免大家的参数组合形式各种各种，使用者需要去区分太多细节。
*/
use crate::data_frame::value::{ConfValue, RealValue, ElementValue, ElementRealConfValue};
use crate::run_plan::{HandResult};
use std::fmt::Debug;

use crate::physical_plan::general::{uuid, time_now, datetime_format, realtype_convert, get_ip_version_element, add_datetime_ms2s_element, trans_vxlan_element, trans_vlan_element, work_space_name, work_node_name};
use crate::physical_plan::filter::{gt, lt, ge, le, eq, exist, is_prefix, regex, like, is_bytes, is_range,
    is_loopback,is_ipv6,is_ipv4,is_unspecified,is_global,is_multicast,is_documentation, is_benchmarking,
    is_ipv4_broadcast,is_ipv4_private,is_ipv4_shared,is_ipv4_reserved,is_ipv4_a_class,is_ipv4_b_class, is_ipv4_c_class,is_linklocal,
    is_datetime,is_year,is_month,is_day,is_hour,is_minute,is_second,is_weekday,is_duration,is_hms,
    is_random};
use crate::physical_plan::simple::set;
use crate::conf_init::{MapResult, MapErr};
use crate::physical_plan::element::*;
use crate::data_frame::single_data::SingleData;

/*
进行事件通用处理的函数的参数
*/
#[derive(Clone,Debug,Hash)]
pub enum PhysicalPlanExprArg {
    ConfValue(ConfValue),
    RealValue(RealValue),
    ElementValue(ElementValue),
}

pub enum PhysicalPlanExprArgOrErr{
    Arg(PhysicalPlanExprArg),
}

macro_rules! physical_func{
    ($name: expr, $func: ident) => {
        MapResult::Ok(Box::new(PhysicalPlanExpr::new($name, $func)))
    }
}

impl PhysicalPlanExprArg {
    pub fn from(value: ElementRealConfValue) -> Box<PhysicalPlanExprArg>{
        match value{
            ElementRealConfValue::ElementValue(value) => {
                Box::new(PhysicalPlanExprArg::ElementValue(value))
            },
            ElementRealConfValue::RealValue(value) => {
                Box::new(PhysicalPlanExprArg::RealValue(value))
            },
            ElementRealConfValue::ConfValue(value) => {
                Box::new(PhysicalPlanExprArg::ConfValue(value))
            },
        }
    }
    pub fn from_real_value(value: RealValue)->Box<PhysicalPlanExprArg>{
        Box::new(PhysicalPlanExprArg::RealValue(value))
    }
}

#[derive(Clone)]
pub struct PhysicalPlanExpr {
    name: String,
    fn_ptr: fn(&[Box<PhysicalPlanExprArg>], data: &mut SingleData) -> HandResult,
}

impl std::fmt::Debug for PhysicalPlanExpr {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("PhysicalPlan")
            .field(&self.name)
            .finish()
    }
}

impl PhysicalPlanExpr {
    fn new(name: &str,
           fn_ptr: fn(&[Box<PhysicalPlanExprArg>], &mut SingleData) -> HandResult)
        -> PhysicalPlanExpr {
        PhysicalPlanExpr {
            name: name.to_string(),
            fn_ptr: fn_ptr,
        }
    }
    pub fn name(&self)->&str{
        return self.name.as_str();
    }
    pub async fn evaluate(&self, args: &[Box<PhysicalPlanExprArg>], data: &mut SingleData) -> HandResult {
        return (self.fn_ptr)(args, data);
    }
}

pub fn logical_plan_expr_try_map_physical_plan_expr(expr: &ElementRealConfValue) -> Box<PhysicalPlanExprArg>{
    match expr{
        ElementRealConfValue::RealValue(value) => {
            return Box::new(PhysicalPlanExprArg::RealValue(value.clone()));
        },
        ElementRealConfValue::ConfValue(value) => {
            return Box::new(PhysicalPlanExprArg::ConfValue(value.clone()));
        },
        ElementRealConfValue::ElementValue(value) => {
            return Box::new(PhysicalPlanExprArg::ElementValue(value.clone()));
        },
    }
}

pub fn logicalplan_try_map_physicalplan(name: &str) -> MapResult<Box<PhysicalPlanExpr>>{
    match name{
        "gt" => {return physical_func!("gt",gt);}
        "lt" => {return physical_func!("lt",lt);}
        "ge" => {return physical_func!("ge", ge);}
        "le" => {return physical_func!("prefix",le);}
        "set" => {return physical_func!("set", set);}
        "uuid" => {return physical_func!("uuid", uuid);}
        "exist" => {return physical_func!("exist",exist);}
        "eq" => {return physical_func!("eq",eq);}
        "is_prefix" => {return physical_func!("is_prefix",is_prefix);}
        "regex" => {return physical_func!("regex", regex);}
        "like" => {return physical_func!("like", like);}
        "is_range" => {return physical_func!("is_range", is_range);}
        "is_bytes" => {return physical_func!("is_bytes", is_bytes);}
        "is_datetime" => {return physical_func!("is_datetime", is_datetime);}
        "is_year" => {return physical_func!("is_year", is_year);}
        "is_weekday" => {return physical_func!("is_weekday", is_weekday);}
        "is_month" => {return physical_func!("is_month", is_month);}
        "is_day" => {return physical_func!("is_day", is_day);}
        "is_hour" => {return physical_func!("is_hour", is_hour);}
        "is_minute" => {return physical_func!("is_minute", is_minute);}
        "is_second" => {return physical_func!("is_second", is_second);}
        "is_duration" => {return physical_func!("is_duration", is_duration);}
        "is_hms" => {return physical_func!("is_hms", is_hms);}
        "is_loopback" => {return physical_func!("is_loopback", is_loopback);}
        "is_ipv6" => {return physical_func!("is_ipv6", is_ipv6);}
        "is_ipv4" => {return physical_func!("is_ipv4", is_ipv4);}
        "is_unspecified" => {return physical_func!("is_unspecified", is_unspecified);}
        "is_global" => {return physical_func!("is_global", is_global);}
        "is_multicast" => {return physical_func!("is_multicast", is_multicast);}
        "is_documentation" => {return physical_func!("is_global", is_documentation);}
        "is_benchmarking" => {return physical_func!("is_benchmarking", is_benchmarking);}
        "is_ipv4_broadcast" => {return physical_func!("is_ipv4_broadcast", is_ipv4_broadcast);}
        "is_ipv4_private" => {return physical_func!("is_ipv4_private", is_ipv4_private);}
        "is_ipv4_shared" => {return physical_func!("is_ipv4_shared", is_ipv4_shared);}
        "is_ipv4_reserved" => {return physical_func!("is_ipv4_reserved", is_ipv4_reserved);}
        "is_ipv4_a_class" => {return physical_func!("is_ipv4_a_class", is_ipv4_a_class);}
        "is_ipv4_b_class" => {return physical_func!("is_ipv4_b_class", is_ipv4_b_class);}
        "is_ipv4_c_class" => {return physical_func!("is_ipv4_c_class", is_ipv4_c_class);}
        "is_linklocal" => {return physical_func!("is_linklocal", is_linklocal);}
        "is_random" => {return physical_func!("is_random", is_random);}
        //func
        "add_element" => {return physical_func!("add_element", add_element);}
        "get_element" => {return physical_func!("get_element", get_element);}
        "convert" => {return physical_func!("convert", convert);}
        "encode" => {return physical_func!("encode", encode);}
        "decode" => {return physical_func!("decode", decode);}
        //general
        "now" => {return physical_func!("time_now", time_now)}
        "datetime_format" => {return physical_func!("datetime_format", datetime_format);}
        "realtype_convert" => {return physical_func!("realtype_convert", realtype_convert);}
        "get_ip_version_element" => {return physical_func!("get_ip_version_element", get_ip_version_element);}
        "add_datetime_ms2s_element" => {return physical_func!("add_datetime_ms2s_element", add_datetime_ms2s_element);}
        "trans_vxlan_element" => {return physical_func!("trans_vxlan_element", trans_vxlan_element);}
        "trans_vlan_element" => {return physical_func!("trans_vlan_element", trans_vlan_element);}
        "space_name" => {return physical_func!("work_space_name", work_space_name);}
        "node_name" => {return physical_func!("work_node_name", work_node_name);}
        other => {
            return MapResult::Err(MapErr::new(format!("func {} not support", other)));
        },
    }
}


